package smlab.loader
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.SecurityDomain;
	import flash.utils.Dictionary;
	
	import smlab.events.LoadListEvent_SM;
	
	[Event(name="complete",type="smlab.events.LoadListEvent_SM")]
	[Event(name="progress",type="smlab.events.LoadListEvent_SM")]
	[Event(name="open",type="smlab.events.LoadListEvent_SM")]
	[Event(name="error",type="smlab.events.LoadListEvent_SM")]
	
	/**
	 * 加载资源管理类（队列加载）
	 * @author simon
	 * 
	 */
	public class LoadList_SM extends EventDispatcher
	{
		/**
		 * 记录每个资源的 url
		 */
		public var urls:Array=[];
		
		/**
		 * 加载资源总个数
		 */
		private var totalResourceNum:int=0;
		
		/**
		 * 当前加载到第几个资源
		 */
		private var currentResourceIndex:int=1;
		
		private var _currentLoader:Loader;
		
		/**
		 * 记录加载出错的 url
		 */
		private var errUrls:Array=[];
		
		/**
		 * 是否正在加载
		 */
		public var isLoading:Boolean=false;
		
		/**
		 * 队列加载结束后是否还有未成功加载的资源（如果有，可以弹出 Alert 提示用户是否重新尝试加载这些资源，执行 loadErrResouce() 即可）
		 */
		public var hasErrResource:Boolean=false;
		
		private var _appDomain:ApplicationDomain;
		private var _checkPolicyFile:Boolean;
		private var _securityDomain:SecurityDomain;
		
		private var _loadingSkin:LoadingPanel_SM;
		private var _isAutoCloseLoading:Boolean=false;
		private static var _instance:LoadList_SM;
		
		public var loaderDict:Dictionary;//根据URL保存Loader的实例，用于队列加载完成后获取loader
		
		/**
		 * 
		 * @param loadingUI$		获取方法示例：LoadingUIManager.mainLoadingUI;
		 * @param defaultMsg$		loading时候显示的文字
		 * @param checkPolicyFile	
		 * @param applicationDomain	
		 * @param securityDomain	
		 * 
		 */
		public function LoadList_SM(loadingUI$:Sprite=null,defaultMsg$:String="",checkPolicyFile:Boolean = false, applicationDomain:ApplicationDomain = null, securityDomain:SecurityDomain = null)
		{
			if(loadingUI$){
				loadingSkin=new LoadingPanel_SM(loadingUI$);
				loadingSkin.defaultMsg=defaultMsg$;
			}
			
			_appDomain=applicationDomain;
			_checkPolicyFile=checkPolicyFile;
			_securityDomain=securityDomain;
			loaderDict=new Dictionary;
		}
		
		
		public static function getInstance():LoadList_SM
		{
			if(!_instance){
				_instance=new LoadList_SM(null,"",true);
			}
			return _instance;
		}
		
		/**
		 * 设置 loading 皮肤，设置为 null 则不显示
		 * @param s
		 * 
		 */
		public function set loadingSkin(s:LoadingPanel_SM):void{
			_loadingSkin=s;
		}
		
		public function get loadingSkin():LoadingPanel_SM{
			return _loadingSkin;
		}
		
		/**
		 * 设置加载完成是否自动隐藏  loading 皮肤
		 * @param s
		 * 
		 */
		public function set isAutoCloseLoading(b:Boolean):void{
			_isAutoCloseLoading=b;
		}
		
		public function get isAutoCloseLoading():Boolean{
			return _isAutoCloseLoading;
		}
		
		public function get loader():Loader{
			return _currentLoader;
		}
		
		/**
		 * 添加一个下载地址
		 * @param url
		 * 
		 */
		public function push(url:String):void{
			if(url && url!=""){
				urls.push(url);
				totalResourceNum += 1;
			}else{
				trace("push_URL_Error:"+url);
			}
		}
		
		/**
		 * 开始队列加载
		 * 
		 */
		public function start():void
		{
			if(urls.length>0){
				isLoading=true;
				var l:Loader=new Loader;
				l.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
				l.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
				l.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
				l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				l.contentLoaderInfo.addEventListener(Event.OPEN, openHandler);
				l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				l.contentLoaderInfo.addEventListener(Event.UNLOAD, unLoadHandler);
				
				var url:String=urls[0];
				_currentLoader=l;
				loaderDict[url]=l;
				l.load(new URLRequest(url),new LoaderContext(_checkPolicyFile,_appDomain,_securityDomain));
			}else{
				trace("没有URL可以加载");
			}
			
		}
		
		/**
		 * 停止所有下载
		 * 
		 */
		public function close(hideUI:Boolean=true):void
		{
			urls=[];
			errUrls=[];
			totalResourceNum=0;
			currentResourceIndex = 1;
			isLoading =false;
			hasErrResource=false;
			loaderDict=null;
			
			if(hideUI){
				if(loadingSkin){
					loadingSkin.hide();
				}
			}
			
			if(_currentLoader)
			{
				try{
					_currentLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, completeHandler);
					_currentLoader.contentLoaderInfo.removeEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
					_currentLoader.contentLoaderInfo.removeEventListener(Event.INIT, initHandler);
					_currentLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
					_currentLoader.contentLoaderInfo.removeEventListener(Event.OPEN, openHandler);
					_currentLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
					_currentLoader.contentLoaderInfo.removeEventListener(Event.UNLOAD, unLoadHandler);
					_currentLoader.close();
					_currentLoader=null;
				}catch(e:*){trace("尝试执行 LoadList_SM.close 方法（该错误无关紧要）:"+e)}
			}
		}
		
		/**
		 * 重新加载出错的资源
		 * 
		 */
		private function loadErrResouce():void{
			totalResourceNum=errUrls.length;
			currentResourceIndex = 1;
			urls=errUrls;
			start();
		}
		
		private function completeHandler(e:Event):void
		{
			var url:String=urls.shift();
			if(urls.length==0){
				isLoading=false;
				hasErrResource=false;
				
				if(isAutoCloseLoading){
					if(loadingSkin){
						loadingSkin.hide();
					}
				}
				//队列中所有任务加载完成
				this.dispatchEvent(new LoadListEvent_SM(LoadListEvent_SM.COMPLETE));
				trace("资源加载完毕");
			}else{
				//队列中的某个加载完成
				this.dispatchEvent(new LoadListEvent_SM(LoadListEvent_SM.COMPLETE_ONE_OF_ALL));
				start();
				trace("已加载完毕的 URL："+url+"\n开始加载下一个："+urls[0]);
			}
			
			currentResourceIndex += 1;
		}
		
		private function ioErrorHandler(e:IOErrorEvent):void
		{
			var tmpUrl:String=urls.shift();
			errUrls.push(tmpUrl);
			hasErrResource=true;
			
			dispatchEvent(new LoadListEvent_SM(LoadListEvent_SM.ERROR));
			
			if(urls.length==0){
				trace("资源加载结束，加载出错的URL为："+tmpUrl);
				isLoading=false;
				dispatchEvent(new LoadListEvent_SM(LoadListEvent_SM.COMPLETE));
			}else{
				trace("资源加载出错！出错的URL为："+tmpUrl+"\n"+"开始加载下一个资源："+urls[0]);
				start();
			}
		}
		
		private function progressHandler(e:ProgressEvent):void
		{
			var event:LoadListEvent_SM=new LoadListEvent_SM(LoadListEvent_SM.PROGRESS);
			event.bytesLoaded=e.bytesLoaded;
			event.bytesTotal=e.bytesTotal;
			event.currentResourceIndex=this.currentResourceIndex;
			event.totalResourceNum=this.totalResourceNum;
			
			if(loadingSkin){
				loadingSkin.showLoading(e.bytesLoaded,e.bytesTotal);
			}
			
			dispatchEvent(event);
		}
		
		private function httpStatusHandler(event:HTTPStatusEvent):void {
			
		}
		
		private function initHandler(event:Event):void {
			
		}
		
		private function openHandler(e:Event):void
		{
			if(loadingSkin){
				loadingSkin.showLoading(0,100);
			}
			
			dispatchEvent(new LoadListEvent_SM(LoadListEvent_SM.OPEN));
		}
		
		private function unLoadHandler(event:Event):void {
			
		}
		
		
	}
}




/*
单例使用示例

LoadingPanel_SM.getInstance().skin=LoadingUIManager.mainLoadingUI;
LoadList_SM.getInstance().loadingSkin=LoadingPanel_SM.getInstance();
sprite.addChild(LoadList_SM.getInstance().loadingSkin);
//以上步骤为单例初始化的时候需要写

LoadList_SM.getInstance().loadingSkin.defaultMsg="正在飞向拉贝尔大陆:";
LoadList_SM.getInstance().push(UI_PATH);
LoadList_SM.getInstance().addEventListener(LoadListEvent_SM.COMPLETE,onLoadUI);
LoadList_SM.getInstance().addEventListener(LoadListEvent_SM.ERROR,failLoadUI);
LoadList_SM.getInstance().start();

*/


/*
实例化使用示例

var l:LoadList_SM=new LoadList_SM(LoadingUIManager.mainLoadingUI);
container.addChild(l.loadingSkin);
l.push(url);
l.addEventListener(LoadListEvent_SM.COMPLETE,onLoadBook);
l.addEventListener(LoadListEvent_SM.ERROR,failLoadBook);
l.start();

private function onLoadBook(eve:LoadListEvent_SM):void
{
var l:LoadList_SM=LoadList_SM(eve.target);
l.removeEventListener(LoadListEvent_SM.COMPLETE,onLoadBook);
l.removeEventListener(LoadListEvent_SM.ERROR,failLoadBook);
l.close();
}

*/